﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Security.Cryptography;

namespace Aliyun.Oss
{
	/// <summary>
	/// Open Storage
	/// </summary>
	public class OpenStorage
	{
		public readonly string OssHeaderPrefix = "X-OSS-";
		/// <summary>
		/// 计算授权签名
		/// 将x-oss开头的排序，转换为小写
		/// 
		/// 目前请求动词仅包括“?group”与“?acl”其中，
		/// DATE和CanonicalizedResource不能为空；
		/// 如果请求中的DATE时间和OSS服务器的时间差15分钟以上，
		/// OSS服务器将拒绝该服务，并返回相应的错误码。
		/// 
		/// 1． 用来签名的字符串为UTF-8格式
		/// 2． 签名的方法用RFC 2104 中定义的HMAC-SHA1方法，其中Key为Accesskey 
		/// 3． content-type和content-md5在请求中不是必须的，但是如果请求需要签名验证，空值的话以回车符代替
		/// 4． 以x-oss-开头的head在签名验证前需要符合以下规范
		///		head的名字需要变成小写
		///		head自小到大排序
		///		分割head name和value的冒号前后不能有空格
		///		每个Head之后都有一个回车，如果没有Head，CanonicalizedOSSHeaders就设置为空
		///		
		/// InvalidAccessKeyId 403 Forbidden
		/// </summary>
		/// <param name="accessId">用户ID</param>
		/// <param name="accessKey">用户安全密钥</param>
		/// <param name="httpMethod">PUT,GET,DELETE</param>
		/// <param name="headers">至少包含Content-Md5,Content-Type,Date(GMT)</param>
		/// <param name="resource">/,/bucket,/bucket/object_name,/buckt?acl,/bucket?group</param>
		/// <returns>signature string.like `OSS 44CF9590006BF252F707: 63mwfl+zYIOG6k95yxbgMruQ6QI=`</returns>
		public string Signature(string accessKey,string httpMethod,
			NameValueCollection headers,string resource = "/")
		{
			string contentMD5 = headers.DefaultOrEmpty("Content-Md5"),
				contentType = headers.DefaultOrEmpty("Content-Type"),
				date = headers.DefaultOrEmpty("Date"),
				canonicalizedResource = resource;
			var h = new NameValueCollection();// ordered lowered oss header
			foreach (string key in headers.AllKeys.OrderBy(k => k))
			{
				if (key.StartsWith(OssHeaderPrefix))
					h.Add(key.ToLower(), headers[key]);
			}

			string canonicalizedOssHeaders = h.KeyValue();

			string fmtText = String.Format("{0}\n{1}\n{2}\n{3}\n{4}{5}",
					httpMethod,
					contentMD5,
					contentType,
					date,
					canonicalizedOssHeaders, // end with \n
					canonicalizedResource);

			var sha1Text = fmtText.SHA1(accessKey);

			return Convert.ToBase64String(sha1Text);
		}

		private string HeaderAuth(string accessId, string signature)
		{
			return String.Format("OSS {0}:{1}", accessId, signature);
		}

		private string UrlAuth(string accessId, string signature)
		{
			var parameters = new
			{
				OSSAccessKeyId = accessId,
				Expires = DateTime.Now.ToFileTimeUtc(),
				Signature = signature // encoded to utf-8 url
			};

			throw new NotImplementedException();
		}

		public void Request(string httpMethod,string resource,bool auth)
		{

		}

		public void Response()
		{

		}
	}
}
